package org.hit.burkun.umls.relation.merge;

import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;

import org.hit.burkun.db.DBHelper;
import org.hit.burkun.entities.Entity;
import org.hit.burkun.entities.Entity.TYPE;
import org.hit.burkun.umls.relation.UniformRelation;

public class DoDiseaseGeneMerge {
	// 考虑来自sidd扩充至后的数据
	/**
	 * 我们认为相同的等级下，MFX>MFS>MFI所以当同时存在时，只是保留最重要的那个而已, step1: 创建视图，这个函数依赖于两个视图
	 * CREATE ALGORITHM = UNDEFINED DEFINER = `root`@`127.0.0.1` SQL SECURITY
	 * DEFINER VIEW `do_sidd_ctd_curated_gene` AS SELECT `a`.`do_id` AS `do_id`,
	 * `a`.`otherdb_id` AS `mesh`, `a`.`mapping_type` AS `mapping_type`,
	 * `b`.`ent2_dbid` AS `ent2_dbid` FROM (`biosearch`.`do_mapping` `a` JOIN
	 * `biodata`.`birelation` `b`) WHERE ((`a`.`otherdb_id` = `b`.`ent1_dbid`)
	 * AND (`a`.`otherdb_type` = 'mesh') AND (`b`.`rel_detial` =
	 * 'disease_ctd_gene_curated')) CREATE ALGORITHM = UNDEFINED DEFINER =
	 * `root`@`127.0.0.1` SQL SECURITY DEFINER VIEW `do_sidd_omim_gene` AS
	 * SELECT `a`.`do_id` AS `do_id`, `a`.`otherdb_id` AS `omim`,
	 * `a`.`mapping_type` AS `mapping_type`, `b`.`ent2_dbid` AS `ent2_dbid` FROM
	 * (`biosearch`.`do_mapping` `a` JOIN `biodata`.`birelation` `b`) WHERE
	 * ((`a`.`otherdb_id` = `b`.`ent1_dbid`) AND (`a`.`otherdb_type` = 'omim')
	 * AND (`b`.`rel_detial` = 'omim_gene'));
	 * 
	 * 这些视图可以获取 do - mapping type - gene的关系，不过确少了clinvar的数据，这里需要添加上去 step 2： do
	 * term do umls gene id
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		/*
		 * mesh1464 omim1173 合并1794 总计1844, 加上clinvar的数据后 1886
		 * 
		 * /不加同义词
		 * 
		 * 103 117 206 387，加上clinvar的后733 不适用MFI，（map from inffer来推导出来的数据有）
		 * ctd可以为do term的103个节点提供基因注释 omim可以为 doterm 的117个提供基因注释 clinvar可以为
		 * doterm的414个term提供基因注释 加上通过do的xref映射到omim2gene上面的221个，
		 * 去重之后有733个do有基因注释
		 */
		HashMap<String, LinkedList<GeneMergeObject>> res = mergeDoAll();
		Collection<String[]> data = StaticMethods
				.formatToEntity2GeneDbRelWithoutPrimaryId(res,
						Entity.TYPE.DISEASE_ONTOLOGY);
		StaticMethods.dumpRelationsWithoutPrimaryId(data, "merge_birelation");
	}

	private static HashMap<String, LinkedList<GeneMergeObject>> mergeDoAll() {
		HashMap<String, LinkedList<GeneMergeObject>> oldRes = StaticMethods
				.getEntity2Entity(UniformRelation.TYPE.DO_XREF_OMIM_GENE);
		HashMap<String, LinkedList<GeneMergeObject>> newRes1 = getSiddMap(TYPE.MSH);
		HashMap<String, LinkedList<GeneMergeObject>> newRes2 = getSiddMap(TYPE.OMIM);
		HashMap<String, LinkedList<GeneMergeObject>> newRes3 = StaticMethods
				.mergeFromEntityByUmls(Entity.TYPE.DISEASE_ONTOLOGY, UniformRelation.TYPE.DISEASE_CLINVAR_GENE);
		//omim,--bug fixed 
		HashMap<String, LinkedList<GeneMergeObject>> newRes4 = StaticMethods
						.mergeFromEntityByUmls(Entity.TYPE.DISEASE_ONTOLOGY, UniformRelation.TYPE.OMIM_GENE);
		HashMap<String, LinkedList<GeneMergeObject>> newRes = StaticMethods
				.merge(newRes1, newRes2);
		newRes = StaticMethods.merge(newRes3, newRes);
		oldRes = StaticMethods.merge(newRes, oldRes);
		oldRes = StaticMethods.merge(newRes4, oldRes);
		return oldRes;
	}

	// doid - omim
	// doid - mesh
	// 返回的是 doid 对应的 geneid 和evidence 和 score
	private static HashMap<String, LinkedList<GeneMergeObject>> getSiddMap(
			TYPE type) {
		Collection<String[]> res = null;
		String head = null;
		HashMap<String, LinkedList<GeneMergeObject>> map = new HashMap<>();
		if (type == TYPE.MSH) {
			// 只能从ctd提供的mesh数据获取disease到基因的关系了
			head = "do_sidd_mesh_gene_";
			DBHelper dbh = DBHelper.getLocalBioSearch();
			dbh.connectionDB();
			res = dbh
					.queryData(
							"SELECT do_id,mapping_type,ent2_dbid ,score FROM do_sidd_ctd_curated_gene #where mapping_type = 'MFS' or mapping_type = 'MFX'",
							4);
			dbh.disconnection();
		} else if (type == TYPE.OMIM) {
			head = "do_sidd_omim_gene_";
			DBHelper dbh = DBHelper.getLocalBioSearch();
			dbh.connectionDB();
			res = dbh
					.queryData(
							"SELECT do_id,mapping_type,ent2_dbid ,score FROM do_sidd_omim_gene #where mapping_type = 'MFS' or mapping_type = 'MFX'",
							4);
			dbh.disconnection();
		}
		if (res != null) {
			for (String[] line : res) {
				if (map.containsKey(line[0])) {
					LinkedList<GeneMergeObject> set = map.get(line[0]);
					boolean isContain = false;
					for (GeneMergeObject go : set) {
						if (go.geneid.equals(line[2])) {
							go.evideces.append("," + head + line[1]);
							if (line[3] == null) {
								go.score.append(",null");
							} else {
								go.score.append("," + line[3]);
							}
							isContain = true;
							break;
						}
					}
					if (!isContain) {
						GeneMergeObject go = new GeneMergeObject();
						go.evideces.append(head + line[1]);
						go.geneid = line[2];
						go.score.append(line[3] == null ? "null" : line[3]);
						set.add(go);
					}
				} else {
					LinkedList<GeneMergeObject> set = new LinkedList<>();
					GeneMergeObject go = new GeneMergeObject();
					go.evideces.append(head + line[1]);
					go.geneid = line[2];
					go.score.append(line[3] == null ? "null" : line[3]);
					set.add(go);
					map.put(line[0], set);
				}
			}
		}
		return map;
	}

}
